home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / TERMINAL / SRCS / DOCUMENT.C < prev    next >
Text File  |  1990-11-20  |  10KB  |  399 lines

  1. /*
  2.     Terminal 2.0
  3.     "Document.c"
  4. */
  5.  
  6. #ifdef THINK_C
  7. #include "MacHeaders"
  8. #endif
  9. #ifdef applec
  10. #pragma load ":(Objects):MacHeadersMPW"
  11. #pragma segment Main2
  12. #endif
  13.  
  14. #include "Text.h"
  15. #include "Main.h"
  16. #include "Document.h"
  17. #include "Scroll.h"
  18. #include "File.h"
  19. #include "Serial.h"
  20. #include "CisB.h"
  21. #include "ZModem.h"
  22.  
  23. #define BS        0x08    /* Backspace key */
  24. #define ESC        '`'        /* Used as escape key */
  25.  
  26. /* ----- Draw cursor --------------------------------------------------- */
  27.  
  28. static void DrawCursor(register Point where, Rect frame)
  29. {
  30.     OffsetRect(&frame, where.h, where.v);
  31.     PaintRect(&frame);
  32. }
  33.  
  34. /* ----- Erase character ----------------------------------------------- */
  35.  
  36. static void EraseCharacter(register Point where, Rect frame)
  37. {
  38.     OffsetRect(&frame, where.h, where.v);
  39.     EraseRect(&frame);
  40. }
  41.  
  42. /* ----- Check to see if display window is entirely visible ------------ */
  43.  
  44. static Boolean Visible(register DocumentPeek window)
  45. {
  46.     register RgnHandle rgn1 = NewRgn(), rgn2 = NewRgn();
  47.     register Boolean v;
  48.  
  49.     RectRgn(rgn1, &window->rect);
  50.     SectRgn(rgn1, ((WindowPtr)window)->visRgn, rgn2);
  51.     v = EqualRgn(rgn1, rgn2);
  52.     DisposeRgn(rgn2);
  53.     DisposeRgn(rgn1);
  54.     return v;
  55. }
  56.  
  57. /* ----- Draw message -------------------------------------------------- */
  58.  
  59. static void DrawMessage(register DocumentPeek window)
  60. {
  61.     EraseRect(&window->messRect);
  62.     if (window->mess[0]) {
  63.         MoveTo(window->messRect.left + 3, window->messRect.top + 13);
  64.         DrawString(window->mess);
  65.         FrameRect(&window->messRect);
  66.     }
  67. }
  68.  
  69. /* ----- Make new message ---------------------------------------------- */
  70.  
  71. void MakeMessage(
  72.     register DocumentPeek window,
  73.     register Byte *message)
  74. {
  75.     SetPort((GrafPtr)window);
  76.     memcpy(window->mess, message, message[0] + 1);
  77.     ShowControl(window->messOk);
  78.     DrawMessage(window);
  79. }
  80.  
  81. /* ----- Draw document window ------------------------------------------ */
  82.  
  83. void DrawDocument(
  84.     register DocumentPeek window,
  85.     short delta)                    /* Number of lines to scroll */
  86. {
  87.     register long line1, line2, n;
  88.     register short v;
  89.     Byte s[256];
  90.     Boolean lastLine;
  91.  
  92.     SetPort((GrafPtr)window);
  93.  
  94.     n = GetCtlValue(window->vs);            /* First visible line */
  95.     if (delta > 0) {                        /* Scroll back */
  96.         line1 = n;                            /* First lines in window */
  97.         line2 = line1 + Min(delta, window->linesPage);
  98.     } else {
  99.         if (delta < 0) {                    /* Scroll forward */
  100.             line2 = n + window->linesPage;    /* Last lines in window */
  101.             line1 = line2 - Min(-delta, window->linesPage);
  102.         } else {                            /* Draw all lines in window */
  103.             MoveTo(window->rect.left - 2, window->rect.top - 3);
  104.             LineTo(window->rect.right + 1, window->rect.top - 3);
  105.             DrawMessage(window);
  106.             line1 = n;
  107.             line2 = line1 + window->linesPage;
  108.         }
  109.     }
  110.     MoveTo(window->cursor0.h,
  111.         v = window->cursor0.v + (line1 - n) * window->height);
  112.     TextMode(srcOr);
  113.     while (line1 < line2) {
  114.         lastLine = FindLine(&window->buf, line1, s);
  115.         DrawString(s);
  116.         if (lastLine) {
  117.             DrawCursor(window->cursor, window->character);
  118.             break;
  119.         }
  120.         MoveTo(window->cursor0.h, v += window->height);
  121.         ++line1;
  122.     }
  123. }
  124.  
  125. /* ----- Draw document window after new line received ------------------ */
  126.  
  127. static void DrawDocumentX(register DocumentPeek window)
  128. {
  129.     register long line1, line2;
  130.     register short v;
  131.     register Boolean lastLine;
  132.     register Byte s[256];
  133.     Rect r;
  134.  
  135.     line2 = (line1 = GetCtlValue(window->vs)) + window->linesPage;
  136.     MoveTo(r.left = window->cursor0.h, v = window->cursor0.v);
  137.     TextMode(srcOr);
  138.     r.right = r.left + (window->rect.right - window->rect.left);
  139.     r.top = window->character.top;
  140.     r.bottom = window->character.bottom;
  141.     OffsetRect(&r, 0, v);
  142.     while (line1 < line2) {
  143.         EraseRect(&r);
  144.         r.top += window->height;
  145.         r.bottom += window->height;
  146.         lastLine = FindLine(&window->buf, line1, s);
  147.         DrawString(s);
  148.         if (lastLine)
  149.             break;
  150.         MoveTo(window->cursor0.h, v += window->height);
  151.         ++line1;
  152.     }
  153. }
  154.  
  155. /* ----- Clear capture buffer ------------------------------------------ */
  156.  
  157. void ClearBuffer(void)
  158. {
  159.     register DocumentPeek window = TerminalWindow;
  160.     register TextRecord *p;
  161.  
  162.     if (window->file)
  163.         SysBeep(1);        /* Not while capture file is open! */
  164.     else {
  165.         p = &window->buf;
  166.         p->lines = 1;
  167.         p->firstChar = p->newChar = p->length =
  168.             p->viewChar = p->viewLine = 0;
  169.         (p->text)[0] = '\015';
  170.         window->cursor = window->cursor0;
  171.         SetCtlValue(window->vs, 0);
  172.         AdjustScrollBar(window);
  173.         SetPort((GrafPtr)window);
  174.         EraseRect(&window->rect);
  175.         DrawDocument(window, 0);
  176.     }
  177. }
  178.  
  179. /* ----- Redraw document ----------------------------------------------- */
  180.  
  181. void RedrawDocument(void)
  182. {
  183.     register DocumentPeek window = TerminalWindow;
  184.  
  185.     BeginUpdate((WindowPtr)window);
  186.     DrawDocument(window, 0);
  187.     DrawControls((WindowPtr)window);
  188.     EndUpdate((WindowPtr)window);
  189. }
  190.  
  191. /* ----- Activate document window -------------------------------------- */
  192.  
  193. void ActivateDocument(
  194.     register DocumentPeek window,
  195.     register short activate)
  196. {
  197.     HiliteControl(window->vs, activate ? 0 : 255);
  198.     InitCursor();
  199. }
  200.  
  201. /* ----- Go to next line ----------------------------------------------- */
  202.  
  203. static void NextLine(register DocumentPeek window)
  204. {
  205.     Rect r;
  206.  
  207.     AddNewCharacter(&window->buf, '\015');
  208.     ByteCapture('\015');
  209.     AdjustScrollBar(window);    /* New value/max for scroll bar */
  210.     r = window->rect;
  211.     window->cursor.h = window->cursor0.h;
  212.     if (window->cursor.v < (r.bottom - window->height)) {
  213.         window->cursor.v += window->height;
  214.     } else {                    /* We must scroll */
  215.     
  216.         /* If window->rect is entirely visible, use ScrollRect(),
  217.         which is much faster than the redraw function. */
  218.          if (Visible(window)) {
  219.             register RgnHandle rgn = NewRgn();
  220.             ScrollRect(&r, 0, -window->height, rgn);
  221.             DisposeRgn(rgn);
  222.         } else
  223.             DrawDocumentX(window);
  224.     }
  225.     MoveTo(window->cursor.h, window->cursor.v);
  226. }
  227.  
  228. /* ----- Handle new characters ----------------------------------------- */
  229.  
  230. void NewCharacters(
  231.     register Byte *buffer,
  232.     register short count,
  233.     register Boolean autorx)
  234. {
  235.     register DocumentPeek window = TerminalWindow;
  236.     register Byte *start = buffer;
  237.     register Byte b;
  238.     register short n;
  239.     short width;
  240.     Rect r;
  241.  
  242.     SetPort((GrafPtr)window);
  243.     r = window->rect;
  244.     width = window->character.right - window->character.left;
  245.  
  246.     /* Scroll to end of document if necessary */
  247.  
  248.     {
  249.         ControlPtr c = *(window->vs);
  250.  
  251.         if (n = c->contrlValue - c->contrlMax) {
  252.             AdjustScrollBar(window);
  253.             Scroll(window, n);
  254.         }
  255.     }
  256.  
  257.     /* Erase cursor and set pen position */
  258.  
  259.     MoveTo(window->cursor.h, window->cursor.v);
  260.     EraseCharacter(window->cursor, window->character);
  261.  
  262.     /* Check all characters */
  263.  
  264.     while (count--) {
  265.         b = *buffer++;
  266.  
  267.         /* Check for CompuServe-B */
  268.  
  269.         if (b == ENQ && autorx && Settings.protocol == 1 && !Transfer &&
  270.                 !Sending) {
  271.             if ((n = buffer - start - 1) > 0) {
  272.                 DrawText(start, 0, n);
  273.                 GetPen(&window->cursor);
  274.             }
  275.             start = buffer;
  276.             CisB();
  277.             UnloadSeg(CisB);
  278.             /* Meanwhile progress window was up */
  279.             SetPort((GrafPtr)window);
  280.             MoveTo(window->cursor.h, window->cursor.v);
  281.             continue;
  282.         }
  283.  
  284.         /* Check for ZModem autoreceive string */
  285.  
  286.         if (Settings.ZAutoReceive && autorx && !Transfer && !Sending) {
  287.             memcpy(ZLastRx, ZLastRx + 1, ZAUTORX - 1);
  288.             ZLastRx[ZAUTORX - 1] = b;
  289.             if (!strcmp((char *)ZLastRx, (char *)ZAutoReceiveString)) {
  290.                 if ((n = buffer - start - 1) > 0) {
  291.                     DrawText(start, 0, n);
  292.                     GetPen(&window->cursor);
  293.                 }
  294.                 start = buffer;
  295.                 ZReceive();
  296.                 UnloadSeg(ZReceive);
  297.                 /* Meanwhile progress window was up */
  298.                 SetPort((GrafPtr)window);
  299.                 MoveTo(window->cursor.h, window->cursor.v);
  300.                 continue;
  301.             }
  302.         }
  303.  
  304.         /* Handle backspace character */
  305.  
  306.         if (b == Settings.backspace) {
  307.             if ((n = buffer - start - 1) > 0) {
  308.                 DrawText(start, 0, n);
  309.                 GetPen(&window->cursor);
  310.             }
  311.             start = buffer;
  312.             if (b = RemoveCharacter(&window->buf)) {
  313.                 ByteCapture(Settings.backspace);
  314.                 window->cursor.h -= width;    /* faster than CharWidth(b) */
  315.                 MoveTo(window->cursor.h, window->cursor.v);
  316.                 EraseCharacter(window->cursor, window->character);
  317.             }
  318.             continue;
  319.         }
  320.  
  321.         /* Handle carriage return */
  322.  
  323.         if (b == '\015') {
  324.             if ((n = buffer - start - 1) > 0) {
  325.                 DrawText(start, 0, n);
  326.                 GetPen(&window->cursor);
  327.             }
  328.             start = buffer;
  329.             NextLine(window);
  330.             continue;
  331.         }
  332.  
  333.         /* Filter out control characters */
  334.  
  335.         if (b != '\t' && (b < 0x20 || b > 0x7E)) {
  336.             if (b == 0x07 && Settings.beep)    /* Check for BEL */
  337.                 SysBeep(1);
  338.             if ((n = buffer - start - 1) > 0) {
  339.                 DrawText(start, 0, n);
  340.                 GetPen(&window->cursor);
  341.             }
  342.             start = buffer;
  343.             continue;
  344.         }
  345.  
  346.         /* Handle printable characters */
  347.  
  348.         if (window->cursor.h >= r.right) {
  349.             if ((n = buffer - start - 1) > 0) {
  350.                 DrawText(start, 0, n);
  351.                 GetPen(&window->cursor);
  352.             }
  353.             start = buffer - 1;
  354.             NextLine(window);            /* Insert additional CR */
  355.         } else
  356.             window->cursor.h += width;    /* Faster than CharWidth(b) */
  357.         AddNewCharacter(&window->buf, b);
  358.         ByteCapture(b);
  359.     }
  360.  
  361.     /* Make sure everything is drawn */
  362.  
  363.     if ((n = buffer - start) > 0) {
  364.         DrawText(start, 0, n);
  365.         GetPen(&window->cursor);
  366.     }
  367.  
  368.     /* Draw cursor */
  369.  
  370.     if (window->cursor.h >= r.right)
  371.         NextLine(window);            /* Insert additional CR */
  372.     DrawCursor(window->cursor, window->character);
  373. }
  374.  
  375. /* ----- Handle new character from keyboard ---------------------------- */
  376.  
  377. void NewKey(register Byte key)
  378. {
  379.     register Byte buffer[2];
  380.     register long count;
  381.  
  382.     if (key == BS)
  383.         key = Settings.backspace;
  384.     else if (key == ESC)
  385.         key = Settings.escape;
  386.     buffer[0] = key;
  387.     count = 1;
  388.     if (key == '\015' && Settings.autoLF) {
  389.         buffer[1] = '\012';
  390.         count++;
  391.     }
  392.     while (Busy)    /* Other send in progress */
  393.         ;
  394.     SerialSend(buffer, count, &Busy);
  395.     if (Settings.localEcho)
  396.         NewCharacters(buffer, 1, FALSE);
  397.     CheckEvents();
  398. }
  399.